package com.voicechat.firstmet.client;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.util.Log;

import com.neovisionaries.ws.client.WebSocket;
import com.neovisionaries.ws.client.WebSocketFactory;
import com.voicechat.firstmet.App;
import com.voicechat.firstmet.net.HTTPAPI;
import com.voicechat.firstmet.utils.Utils;

import java.io.IOException;

/**
 * @ProjectName: FirstMet
 * @Package: com.voicechat.firstmet.client
 * @ClassName: WsManager
 * @Description: 长链接管理类
 * @Author: ljp
 * @CreateDate: 2018/11/21 10:26
 * @Version: 1.0
 */
public class WsManager {
    private static WsManager mInstance;
    private static String TAG = "WsManager";
    /**
     * WebSocket config
     */
    /**
     * 心跳检测时间
     */
    public static final long HEART_BEAT_RATE = 60 * 1000;//每隔1分钟进行一次对长连接的心跳检测
    private static final int FRAME_QUEUE_SIZE = 5;
    private static final int CONNECT_TIMEOUT = 5000;
    private static final String DEF_TEST_URL = HTTPAPI.BASE_WS;//测试服默认地址
    private String userid;
    private WebSocket ws;
    private WsListener mListener;
    private  Context context;
    private long sendTime = 0L;
    // 发送心跳包
    private Handler mHandler = new Handler();
    // 发送心跳包
    private Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
                RequestVoiceChatBean requestBean = new RequestVoiceChatBean(20000,null);
                sendMessageHeartbeat(requestBean);
                sendTime = System.currentTimeMillis();
            }
            if (mHandler != null) {
                mHandler.postDelayed(this, HEART_BEAT_RATE); //每隔一定的时间，对长连接进行一次心跳检测
            }
        }
    };
    private WsManager(Context context) {
        this.context = context;
    }

    public void send(){
        mHandler.postDelayed(heartBeatRunnable, 0);
    }
    public static WsManager getInstance(Context context){
        if(mInstance == null){
            synchronized (WsManager.class){
                if(mInstance == null){
                    mInstance = new WsManager(context);
                }
            }
        }
        return mInstance;
    }

    public String getUserid() {
        return userid;
    }
    /**
    * @method
    * @description 建立链接
    * @date: 2018/11/21 11:18
    * @author: ljp
    * @return
    */
    public void init(String id){
        userid = id;
        try {
            Log.i(TAG, "init: -------"+DEF_TEST_URL+id);
            ws = new WebSocketFactory().createSocket(DEF_TEST_URL+id, CONNECT_TIMEOUT)
                    .setFrameQueueSize(FRAME_QUEUE_SIZE)//设置帧队列最大值为5
                    .setMissingCloseFrameAllowed(false)//设置不允许服务端关闭连接却未发送关闭帧
                    .addListener(mListener = new WsListener())
                    .connectAsynchronously();//异步连接
            mListener.setStatus(WsListener.WsStatus.CONNECTING);
            send();
           // Logger.t(TAG).d("第一次连接");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public  void  getWsOpen(){
        if(ws != null) {
            ws.isOpen();
        }
    }
    /**
     * @method
     * @description 发送心跳包
     * @date: 2018/11/22 16:49
     * @author: ljp
     * @return
     */
    public void sendMessageHeartbeat(RequestVoiceChatBean requestBean){
        if(ws != null && ws.isOpen()){
            //Log.i(TAG, "sendMessage: ---------"+Utils.toJson(requestBean));
            ws.sendText(Utils.toJson(requestBean));
        }
    }
    /**
    * @method
    * @description 发送语音聊天扣款消息
    * @date: 2018/11/22 16:49
    * @author: ljp
    * @return
    */
    public  void  sendMessage(RequestVoiceChatBean requestBean){
        //Log.i(TAG, "sendMessage: ---------"+Utils.toJson(requestBean));
        ws.sendText(Utils.toJson(requestBean));
    }
    /**
    * @method
    * @description 发送礼物消息
    * @date: 2018/11/22 16:50
    * @author: ljp
    * @return
    */
    public  void  sendMessageGift(RequestSendGiftBean requestSendGiftBean,String name){
        //Log.i(TAG, "sendMessage: ---------"+Utils.toJson(requestSendGiftBean)+"--giftName---"+name);
        ws.sendText(Utils.toJson(requestSendGiftBean));
    }
    /**
    * @method
    * @description 断开链接
    * @date: 2018/11/21 11:04
    * @author: ljp
    * @return
    */
    public void disconnect(){
        if(ws != null)
            ws.disconnect();
    }

    private int reconnectCount = 0;//重连次数
    private long minInterval = 3000;//重连最小时间间隔
    private long maxInterval = 60000;//重连最大时间间隔

    /**
    * @method
    * @description 重新链接
    * @date: 2018/11/21 11:04
    * @author: ljp
    * @return
    */
    public void reconnect(String userid) {
       // Log.i(TAG, "init: -------"+DEF_TEST_URL+userid);
        this.userid = userid;
        if (!isNetConnect()) {
            reconnectCount = 0;
            Log.d(TAG,"重连失败网络不可用");
            return;
        }
        //Log.i(TAG, "reconnect: -----isOpen----"+ws.isOpen());
        //这里其实应该还有个用户是否登录了的判断 因为当连接成功后我们需要发送用户信息到服务端进行校验
        if (ws != null &&
                !ws.isOpen() &&//当前连接断开了
                mListener.getStatus() != WsListener.WsStatus.CONNECTING) {//不是正在重连状态
            reconnectCount++;
            mListener.setStatus(WsListener.WsStatus.CONNECTING);
            long reconnectTime = minInterval;
            if (reconnectCount > 3) {
                long temp = minInterval * (reconnectCount - 2);
                reconnectTime = temp > maxInterval ? maxInterval : temp;
            }
            Log.i(TAG,"准备开始第%d次重连,重连间隔%d -- url:%s"+reconnectCount +reconnectTime+DEF_TEST_URL+userid);
            mHandler.postDelayed(mReconnectTask, reconnectTime);
        }
    }
    private Runnable mReconnectTask = new Runnable() {
        @Override
        public void run() {
            try {
                ws = new WebSocketFactory().createSocket(DEF_TEST_URL+userid, CONNECT_TIMEOUT)
                        .setFrameQueueSize(FRAME_QUEUE_SIZE)//设置帧队列最大值为5
                        .setMissingCloseFrameAllowed(false)//设置不允许服务端关闭连接却未发送关闭帧
                        .addListener(mListener = new WsListener())//添加回调监听
                        .connectAsynchronously();//异步连接
                send();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
    /**
    * @method
    * @description 取消重连
    * @date: 2018/11/21 10:42
    * @author: ljp
    * @return
    */
    private void cancelReconnect() {
        reconnectCount = 0;
        mHandler.removeCallbacks(mReconnectTask);
    }


    private boolean isNetConnect() {
        ConnectivityManager connectivity = (ConnectivityManager) App.getContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo info = connectivity.getActiveNetworkInfo();
            if (info != null && info.isConnected()) {
                // 当前网络是连接的
                if (info.getState() == NetworkInfo.State.CONNECTED) {
                    // 当前所连接的网络可用
                    return true;
                }
            }
        }
        return false;
    }

}


